package com.ts.system.service.impl;

import com.google.common.collect.Maps;
import com.ts.animal.constant.AnimalConstant;
import com.ts.common.config.TsConfig;
import com.ts.common.domain.Tree;
import com.ts.common.utils.BuildTree;
import com.ts.common.utils.DataPerUitl;
import com.ts.system.dao.DeptDao;
import com.ts.system.dao.ExDeptDao;
import com.ts.system.domain.DeptDO;
import com.ts.system.service.DeptService;
import com.ts.system.util.SystemUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptDao sysDeptMapper;
    @Autowired
    private ExDeptDao exSysDeptMapper;

    @Override
    public DeptDO get(Long deptId) {
        return sysDeptMapper.get(deptId);
    }

    @Override
    public List<Map<String, Object>> list(Map<String, Object> map) {
        boolean checkLabelSwitch = AnimalConstant.open.equals(SystemUtil.getSystemParams().get(AnimalConstant.key_name_check_label_switch).getParamValue());
        if (checkLabelSwitch) {
            map.put(AnimalConstant.open_label_switch, AnimalConstant.open);
        }
        return exSysDeptMapper.list(map);
    }

    @Override
    public List<DeptDO> subList(Map<String, Object> map) {
        map.putAll(DataPerUitl.deptPer());
        map.put("sort", "select_order");
//    	map.put("order", "select_order");
        List<DeptDO> list = exSysDeptMapper.subList(map);
        return list;
    }

    @Override
    public int count(Map<String, Object> map) {
        return sysDeptMapper.count(map);
    }

    @Override
    public int save(DeptDO sysDept) {
        DeptDO pSysDept = sysDeptMapper.get(sysDept.getParentId());
        sysDept.setLevel(pSysDept.getLevel() + 1);
        String pre = "000";
        String end = "000";
        if (sysDept.getOrderNum() != null) {
            pre = pre + sysDept.getOrderNum();
            pre = pre.substring(pre.length() - 3, pre.length());
        }
        int maxEnd = 0;
        Map<String, Object> map = Maps.newHashMap();
        map.put("parentId", sysDept.getParentId());
        List<DeptDO> list = exSysDeptMapper.listIncludeChildren(map);
        for (DeptDO deptDO : list) {
            String cSelctOrder = deptDO.getSelectOrder();
            cSelctOrder = cSelctOrder.substring(cSelctOrder.length() - 6, cSelctOrder.length());
            String cPre = cSelctOrder.substring(0, 3);
            String cEnd = cSelctOrder.substring(3, 6);
            if (cPre.equals(pre)) {
                int cEndInt = Integer.valueOf(cEnd);
                if (maxEnd <= cEndInt) {
                    maxEnd = cEndInt;
                }
            }
        }
        end = end + (maxEnd + 1);
        end = end.substring(end.length() - 3, end.length());
        String selectOrder = pSysDept.getSelectOrder();
        selectOrder = selectOrder + pre + end;
        sysDept.setSelectOrder(selectOrder);
        String appid = RandomStringUtils.randomAlphanumeric(8);
        String secret = UUID.randomUUID().toString().replaceAll("-", "");
        sysDept.setAppid(appid);
        sysDept.setSecret(secret);
        int ret = sysDeptMapper.save(sysDept);
        SystemUtil.setIdDepts(depts());
        return ret;
    }

    @Override
    public int update(DeptDO sysDept) {

        DeptDO oldSysDept = sysDeptMapper.get(sysDept.getDeptId());
        if (oldSysDept.getOrderNum() != sysDept.getOrderNum() && oldSysDept.getDeptId() != Long.valueOf(TsConfig.getProperty("ts.manage.maxOrg"))) {
            String pre = "000";
            String end = "000";
            if (sysDept.getOrderNum() != null) {
                pre = pre + sysDept.getOrderNum();
                pre = pre.substring(pre.length() - 3, pre.length());
            }
            int maxEnd = 0;
            Map<String, Object> map = Maps.newHashMap();
            map.put("parentId", sysDept.getParentId());
            List<DeptDO> list = exSysDeptMapper.listIncludeChildren(map);
            for (DeptDO deptDO : list) {
                String cSelctOrder = deptDO.getSelectOrder();
                cSelctOrder = cSelctOrder.substring(cSelctOrder.length() - 6, cSelctOrder.length());
                String cPre = cSelctOrder.substring(0, 3);
                String cEnd = cSelctOrder.substring(3, 6);
                if (cPre.equals(pre)) {
                    int cEndInt = Integer.valueOf(cEnd);
                    if (maxEnd <= cEndInt && deptDO.getDeptId() != sysDept.getDeptId()) {
                        maxEnd = cEndInt;
                    }
                }
            }
            end = end + (maxEnd + 1);
            end = end.substring(end.length() - 3, end.length());
            String selectOrder = oldSysDept.getSelectOrder();
            selectOrder = selectOrder.substring(0, selectOrder.length() - 6) + pre + end;
            sysDept.setSelectOrder(selectOrder);
        }

        int ret = sysDeptMapper.update(sysDept);
        SystemUtil.setIdDepts(depts());
        return ret;
    }

    @Override
    public int remove(Long deptId) {
        int ret = sysDeptMapper.remove(deptId);
        SystemUtil.setIdDepts(depts());
        return ret;
    }

    @Override
    public int batchRemove(Long[] deptIds) {
        int ret = sysDeptMapper.batchRemove(deptIds);
        SystemUtil.setIdDepts(depts());
        return ret;
    }

    @Override
    public Tree<DeptDO> getTree() {
        List<Tree<DeptDO>> trees = new ArrayList<Tree<DeptDO>>();
        List<DeptDO> sysDepts = exSysDeptMapper.listIncludeChildren(new HashMap<String, Object>(16));
        for (DeptDO sysDept : sysDepts) {
            Tree<DeptDO> tree = new Tree<DeptDO>();
            tree.setId(sysDept.getDeptId().toString());
            tree.setParentId(sysDept.getParentId().toString());
            tree.setText(sysDept.getName());
            Map<String, Object> state = new HashMap<>(16);
            state.put("opened", true);
            tree.setState(state);
            trees.add(tree);
        }
        // 默认顶级菜单为０，根据数据库实际情况调整
        Tree<DeptDO> t = BuildTree.build(trees);
        return t;
    }


    @Override
    public Map<String, Object> depts() {
        Map<Long, DeptDO> idMap = new HashMap<Long, DeptDO>();
        Map<String, DeptDO> appidMap = new HashMap<String, DeptDO>();
        List<DeptDO> sysDepts = exSysDeptMapper.listIncludeChildren(new HashMap<String, Object>(16));
        for (DeptDO sysDept : sysDepts) {
            idMap.put(sysDept.getDeptId(), sysDept);
            appidMap.put(sysDept.getAppid(), sysDept);
        }
        for (DeptDO sysDept : sysDepts) {
            String name = sysDeptNames(sysDept.getDeptId(), sysDept.getName(), idMap);
            sysDept.setName(name);
        }

        Map<String, Object> ret = new HashMap<>(2);
        ret.put("id", idMap);
        ret.put("appid", appidMap);
        return ret;
    }


    private String sysDeptNames(long id, String name, Map<Long, DeptDO> cpDeptMap) {
        DeptDO sysDept = cpDeptMap.get(id);
        if (sysDept.getLevel() > 2) {
            DeptDO parentDeptDO = cpDeptMap.get(sysDept.getParentId());
            name = parentDeptDO.getName() + " - " + name;
            name = sysDeptNames(parentDeptDO.getDeptId(), name, cpDeptMap);
        }
        return name;
    }


    @Override
    public boolean checkDeptHasUser(Long deptId) {
        //查询部门以及此部门的下级部门
        int result = exSysDeptMapper.getDeptUserNumber(deptId);
        return result == 0 ? true : false;
    }

    @Override
    public List<Long> listChildrenIds(Long parentId) {
        List<DeptDO> deptDOS = exSysDeptMapper.listIncludeChildren(null);
        return treeMenuList(deptDOS, parentId);
    }

    List<Long> treeMenuList(List<DeptDO> menuList, long pid) {
        List<Long> childIds = new ArrayList<>();
        for (DeptDO mu : menuList) {
            //遍历出父id等于参数的id，add进子节点集合
            if (mu.getParentId() == pid) {
                //递归遍历下一级
                treeMenuList(menuList, mu.getDeptId());
                childIds.add(mu.getDeptId());
            }
        }
        return childIds;
    }

}
